import { useEffect, useState } from 'react';
import { Upload, Button, Tooltip, Modal } from 'antd';
import { UploadOutlined, PlusOutlined } from '@ant-design/icons';
import type { UploadChangeParam } from 'antd/lib/upload';
import type { UploadFile, UploadListType } from 'antd/lib/upload/interface';
import { getToken } from '@/utils/auth';
import type { FileType } from '@/services/global/type';

import styles from './style.less';

type Tip = string | React.ReactNode;

type Props = {
  type: string;
  extraParams?: Record<string, unknown>;
  tip?: Tip;
  uploadTip?: string;
  listType?: UploadListType;
  value?: FileType[];
  onChange?: (fileList: FileType[], file?: FileType) => void;
  [key: string]: any;
};

const FileUpload: React.FC<Props> = ({
  type,
  extraParams,
  tip,
  uploadTip,
  value,
  listType = 'picture',
  onChange,
  ...restProps
}) => {
  const { maxCount, disabled, outControlled, removeAfterUpload } = restProps;
  const [{ previewVisible, previewImage, previewTitle }, setPreviewData] = useState({
    previewVisible: false,
    previewImage: '',
    previewTitle: '',
  });

  const formatPropsValueToList = (propsValue: FileType[] = []) => {
    return (
      propsValue?.map((item) => {
        const filePath = item.photoPath || item.mediaPath || item.licensePath;
        const fileUrl = item.photoUrl || item.mediaUrl || item.licenseUrl;
        return {
          uid: filePath,
          name: filePath,
          status: 'done',
          url: fileUrl,
          response: {
            data: item,
          },
        };
      }) || []
    );
  };

  // const defaultFileList = [...formatPropsValueToList(value)];
  const [fileList, setFileList] = useState<UploadFile[]>([]);

  useEffect(() => {
    setFileList(formatPropsValueToList(value) as UploadFile[]);
  }, [value]);

  const getFileList = (files: UploadFile[]) => {
    return files.map((item) => {
      const responseData = { ...item.response.data };
      return {
        ...responseData,
        ...extraParams,
      };
    });
  };

  const allFilesUploaded = (files: UploadFile[]) => {
    return files.every((file) => file.status === 'done');
  };

  const handleChange = ({ file, fileList: files }: UploadChangeParam<UploadFile<any>>) => {
    if (allFilesUploaded(files) && onChange) {
      const list = getFileList(files);
      onChange(list, { ...file.response.data, ...extraParams });
      if (removeAfterUpload) {
        setFileList([]);
      } else {
        setFileList(files);
      }
    } else {
      setFileList(files);
    }
  };

  const onRemove = (file: UploadFile) => {
    const files = fileList.filter((item) => {
      const itemData = item.response?.data;
      const fileData = file.response?.data;
      if (!itemData) {
        return false;
      }
      return (
        itemData.photoPath !== fileData.photoPath ||
        itemData.mediaPath !== fileData.mediaPath ||
        itemData.licensePath !== fileData.licensePath
      );
    });
    setFileList([...files]);
    if (!outControlled && onChange) {
      onChange(getFileList(files));
    }
  };

  const getUploadButton = (buttonListType: UploadListType, tips?: Tip) => {
    const tipsNode = (
      <>
        {tips && <div className={styles.uploadTip}>{tips}</div>}
        <div className={`${styles.uploadTip} ${disabled ? styles.warningTip : ''}`}>
          {uploadTip || '只能上传jpg/png文件'}
        </div>
      </>
    );
    switch (buttonListType) {
      case 'picture':
      case 'text':
        return (
          <>
            <Button icon={<UploadOutlined />} disabled={disabled}>
              点击上传或将文件拖到此处
            </Button>
            {tipsNode}
          </>
        );
      case 'picture-card':
        return (
          <Tooltip title={tipsNode}>
            <div className={styles.uploadPicContent}>
              <div>
                <PlusOutlined />
                <div style={{ marginTop: 8 }}>点击上传或将文件拖到此处</div>
              </div>
            </div>
          </Tooltip>
        );
      default:
        return <></>;
    }
  };

  const handlePreview = (file: UploadFile) => {
    if (file.response?.data.photoUrl) {
      setPreviewData({
        previewVisible: true,
        previewImage: file.response?.data.photoUrl || '',
        previewTitle: file.name?.split('.')[0],
      });
    }
  };

  return (
    <>
      <Upload
        name="file"
        action={`/api/cos/uploadFile?type=${type}`}
        // defaultFileList={fileList}
        fileList={fileList}
        listType={listType}
        accept="image/png, image/jpeg"
        multiple={Number(maxCount) !== 1}
        headers={{ Authorization: getToken() }}
        withCredentials={true}
        className={listType === 'picture' ? styles.uploadList : ''}
        onChange={handleChange}
        onPreview={handlePreview}
        onRemove={onRemove}
        {...restProps}
      >
        {getUploadButton(listType, tip)}
      </Upload>
      <Modal
        visible={previewVisible}
        title={previewTitle}
        footer={null}
        onCancel={() => {
          setPreviewData({
            previewVisible: false,
            previewImage: '',
            previewTitle: '',
          });
        }}
      >
        <img alt="example" style={{ width: '100%' }} src={previewImage} />
      </Modal>
    </>
  );
};

export default FileUpload;
